package com.example.ortools.start.cp;

import com.alibaba.fastjson.JSON;

import java.math.BigDecimal;
import java.util.*;

/**
 * @author: peng.li
 * @date: 2024/09/11
 * @description:
 */
public class OldExample {
    public static void main(String[] args) {
        // 原始数据结构示例
        List<MergeData> req = new ArrayList<>();
        MergeData mergeData = new MergeData();
        mergeData.setGoodsSpecCombinationROList(Arrays.asList(
                new GoodsSpecCombinationRO(11L,null,"规格1",new BigDecimal("2"),new BigDecimal("8"),null),
                new GoodsSpecCombinationRO(22L,null,"规格2",new BigDecimal("1"),new BigDecimal("6"),null),
                new GoodsSpecCombinationRO(33L,null,"规格3",new BigDecimal("1"),new BigDecimal("5"),null)
        ));
        MergeData mergeData1 = new MergeData();
        mergeData1.setGoodsSpecCombinationROList(Arrays.asList(
                new GoodsSpecCombinationRO(33L,null,"规格3",new BigDecimal("1"),new BigDecimal("5"),null),
                new GoodsSpecCombinationRO(44L,null,"规格4",new BigDecimal("1"),new BigDecimal("4"),null)
        ));
        MergeData mergeData2 = new MergeData();
        mergeData2.setGoodsSpecCombinationROList(Arrays.asList(
                new GoodsSpecCombinationRO(55L,null,"规格5",new BigDecimal("1"),new BigDecimal("153"),null),
                new GoodsSpecCombinationRO(66L,null,"规格6",new BigDecimal("3"),new BigDecimal("61"),null)
        ));
        MergeData mergeData3 = new MergeData();
        mergeData3.setGoodsSpecCombinationROList(Arrays.asList(
                new GoodsSpecCombinationRO(44L,null,"规格4",new BigDecimal("1"),new BigDecimal("4"),null),
                new GoodsSpecCombinationRO(77L,null,"规格7",new BigDecimal("3"),new BigDecimal("5"),null)
        ));
        req.add(mergeData);
        req.add(mergeData1);
        req.add(mergeData2);
        req.add(mergeData3);
        System.out.println(JSON.toJSONString(req));
        //规格id最大数量限制
        Map<Long, Tuple<BigDecimal, BigDecimal>> specIdMaxNumLimit = new HashMap<>();
        specIdMaxNumLimit.put(11L,new Tuple<>(new BigDecimal("3242123"),BigDecimal.ZERO));
        specIdMaxNumLimit.put(22L,new Tuple<>(new BigDecimal("4382446"),BigDecimal.ZERO));
        specIdMaxNumLimit.put(33L,new Tuple<>(new BigDecimal("2647121"),BigDecimal.ZERO));
        specIdMaxNumLimit.put(44L,new Tuple<>(new BigDecimal("2284643"),BigDecimal.ZERO));
        specIdMaxNumLimit.put(55L,new Tuple<>(new BigDecimal("4827343"),BigDecimal.ZERO));
        specIdMaxNumLimit.put(66L,new Tuple<>(new BigDecimal("7923423"),BigDecimal.ZERO));
        specIdMaxNumLimit.put(77L,new Tuple<>(new BigDecimal("2342891"),BigDecimal.ZERO));


        OldExample.oldSolver(specIdMaxNumLimit,req);
        System.out.println(JSON.toJSONString(specIdMaxNumLimit));
        BigDecimal total = BigDecimal.ZERO;
        for (Map.Entry<Long, Tuple<BigDecimal, BigDecimal>> longTupleEntry : specIdMaxNumLimit.entrySet()) {
            total = total.add(longTupleEntry.getValue().getB());
        }
        System.out.println(total);
    }

    public static void oldSolver(Map<Long, Tuple<BigDecimal, BigDecimal>> specQuantityMap,List<MergeData> req){
        long startTime = System.currentTimeMillis();
        for (MergeData mergeData : req) {
            List<GoodsSpecCombinationRO> specList = mergeData.getGoodsSpecCombinationROList();
            int[] quantities = calcSpecCombinationQty(specList, specQuantityMap);
            for(int i = 0; i < specList.size(); i++) {
                GoodsSpecCombinationRO spec = specList.get(i);
                Tuple<BigDecimal, BigDecimal> qty = specQuantityMap.get(spec.getGoodsSpecId());
                qty.setB(qty.getB().add(BigDecimal.valueOf(quantities[i]).multiply(spec.getSplitUseRatio())));
            }
        }
        long endTime = System.currentTimeMillis();
        long executionTime = endTime - startTime;
        System.out.println("方法执行时间：" + executionTime + "毫秒");
    }

    /**
     * 计算最优规格组合数量
     */
    public static int[] calcSpecCombinationQty(List<GoodsSpecCombinationRO> specList, Map<Long, Tuple<BigDecimal, BigDecimal>> specQuantityMap) {
        int[] result = new int[specList.size()];
        GoodsSpecCombinationRO firstSpec = specList.get(0);
        Tuple<BigDecimal, BigDecimal> firstQuantity = specQuantityMap.get(firstSpec.getGoodsSpecId());
        result[0] = firstQuantity.getA().subtract(firstQuantity.getB()).divideToIntegralValue(firstSpec.getSplitUseRatio()).intValue();
        for(int i = 1; i < specList.size(); i++) {
            GoodsSpecCombinationRO spec = specList.get(i);
            Tuple<BigDecimal, BigDecimal> specQuantity = specQuantityMap.get(spec.getGoodsSpecId());
            int qty = specQuantity.getA().subtract(specQuantity.getB()).divideToIntegralValue(spec.getSplitUseRatio()).intValue();
            specFlag:
            for (int m = result[0]; m >= 0; m--) {
                for (int n = qty; n >= 0; n--) {
                    Long mQty = Math.round(m * firstSpec.getSplitUseRatio().doubleValue() * spec.getRatio().doubleValue() * 10 * ScaleConstant.SPEC_COMBINATION_CALC_SCALE);
                    Long nQty = Math.round(n * spec.getSplitUseRatio().doubleValue() * firstSpec.getRatio().doubleValue() * 10 * ScaleConstant.SPEC_COMBINATION_CALC_SCALE);
                    int r = mQty.compareTo(nQty);
                    if (r < 0) {
                        continue;
                    }
                    if (r > 0) {
                        break;
                    }
                    result[i] = n;
                    if(result[0] != m) {
                        // 首个规格数量变化，重新计算
                        i = 0;
                        result[0] = m;
                    }
                    break specFlag;
                }
            }
        }
        return result;
    }
}
